﻿#region -- 版 本 注 释 --
/****************************************************
* 文 件 名：
* Copyright(c) 王树羽
* CLR 版本: 4.5
* 创 建 人：王树羽
* 电子邮箱：674613047@qq.com
* 官方网站：https://www.cnblogs.com/shuyu
* 创建日期：2019-05-09 
* 文件描述：
******************************************************
* 修 改 人：
* 修改日期：
* 备注描述：
*******************************************************/
#endregion


using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace CommonLib.Extended
{
    /// <summary>
    /// 实体对象扩展
    /// </summary>
    public static class EntityExtended
    {
        #region 赋值扩展

        /// <summary>
        /// 父级赋值子级操作 扩展
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="K"></typeparam>
        /// <param name="source">原始数据对象</param>
        /// <param name="target">目标对象</param>
        /// <returns></returns>
        public static K ExToEntity<T, K>(this T source, K target) where T : class, new() where K : class
        {
            if (source != null && target != null)
            {
                PropertyInfo[] propertys1 = source.GetType().GetProperties();// 获得此模型的公共属性
                PropertyInfo[] propertys = target.GetType().GetProperties();
                foreach (PropertyInfo pi in propertys)
                {
                    if (pi.CanWrite && propertys1.Where(ex => ex.Name == pi.Name).Count() > 0)
                    {
                        object value = GetProperty(source, pi.Name);
                        pi.SetValue(target, value, null);
                    }
                }
            }
            return target;
        }

        /// <summary>
        /// List父级赋值给子级 扩展
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="K"></typeparam>
        /// <param name="source">源数据对象</param>
        /// <param name="target">赋值目标对象</param>
        public static List<K> ExListToEntity<T, K>(this List<T> source, List<K> target) where T : class, new() where K : class, new()
        {
            if (source != null && target != null)
            {
                foreach (var item in source)
                {
                    var obj = new K();
                    item.ExToEntity(obj);
                    target.Add(obj);
                }
                return target;
            }
            return null;
        }


        /// <summary>
        /// 实体获取属性值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="Name"></param>
        /// <returns></returns>
        public static object GetProperty<T>(T source, string Name) where T : class, new()
        {
            PropertyInfo[] propertys = source.GetType().GetProperties();// 获得此模型的公共属性
            PropertyInfo pi = propertys.Where(ex => ex.Name == Name).FirstOrDefault();
            if (pi != null)
            {
                try
                {
                    return pi.GetValue(source, null);
                }
                catch (Exception)
                {
                }
            }
            return null;
        }
        #endregion

        #region DataTable转IList 扩展

        /// <summary>
        /// DataTable转IList集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dataTable"></param>
        /// <returns></returns>
        public static IList<T> ExToList<T>(this DataTable dataTable) where T : class, new()
        {
            IList<T> list = new List<T>();// 定义集合
            if (dataTable != null)
            {
                foreach (DataRow dr in dataTable.Rows)
                {
                    T t = new T();
                    PropertyInfo[] propertys = t.GetType().GetProperties();// 获得此模型的公共属性
                    foreach (PropertyInfo pi in propertys)
                    {
                        var name = pi.Name;
                        if (dataTable.Columns.Contains(name))
                        {
                            if (!pi.CanWrite) continue;
                            object value = dr[name];
                            if (value != DBNull.Value)
                            {
                                pi.SetValue(t, value, null);
                            }
                        }
                    }
                    list.Add(t);
                }
            }
            return list;
        }
        #endregion

        #region List<T>集合转DataTable 扩展

        /// <summary>
        /// List T 集合转DataTable 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <returns></returns>
        public static DataTable ExToDataTable<T>(this List<T> list) where T : class, new()
        {
            var Dt = new DataTable(typeof(T).Name);
            PropertyInfo[] propertyInfo = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (PropertyInfo prop in propertyInfo)
            {
                Type t = GetCoreType(prop.PropertyType);
                Dt.Columns.Add(prop.Name, t);
            }

            foreach (T item in list)
            {
                var values = new object[propertyInfo.Length];
                for (int i = 0; i < propertyInfo.Length; i++)
                {
                    values[i] = propertyInfo[i].GetValue(item, null);
                }
                Dt.Rows.Add(values);
            }
            return Dt;
        }

        /// <summary>
        /// 如果类型为空否则返回类型返回基本类型
        /// </summary>
        private static Type GetCoreType(Type t)
        {
            var flag = !t.IsValueType || (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>));//判断属性是否为空
            if (t != null && flag)
            {
                if (t.IsValueType)//值类型
                {
                    return Nullable.GetUnderlyingType(t);
                }
            }
            return t;
        }

        #endregion
    }
}
